
package com.emser.unc.client.helper;

import com.emser.unc.client.CloudMobile;
import com.emser.unc.client.event.LogoutEvent;
import com.emser.unc.shared.exception.NotLoggedInException;
import com.google.gwt.http.client.RequestTimeoutException;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.client.rpc.SerializationException;

public abstract class RPCCall<T> implements AsyncCallback<T> {

  protected abstract void callService(AsyncCallback<T> cb);

  private void call(final int retriesLeft) {

    callService(new AsyncCallback<T>() {
      public void onFailure(Throwable caught) {
        try {
          throw caught;
        } catch (InvocationException invocationException) {          
          if (retriesLeft <= 0) {
            RPCCall.this.onFailure(invocationException);
          } else {
            call(retriesLeft - 1); 
          }
        
        } catch (IncompatibleRemoteServiceException remoteServiceException) {
          Window.alert(CloudMobile.constants.eIncompatibleRS());
        } catch (SerializationException serializationException) {
          Window.alert(CloudMobile.constants.eSerialization());
        } catch (NotLoggedInException e) {
          CloudMobile.get().getEventBus().fireEvent(new LogoutEvent());
        } catch (RequestTimeoutException e) {
          Window.alert(CloudMobile.constants.eTimeOut());
        } catch (Throwable e) {
          RPCCall.this.onFailure(e);
        }
          
      }

      public void onSuccess(T result) {
        RPCCall.this.onSuccess(result);
      }
    });
  }

  public void retry(int retryCount) {
    call(retryCount);
  }
}
